import { mergeOptionsHooks, mergeParallelHooks, mergeRollupPlugin } from '../rollup/merge'

const mergeArrayOptionsHooks = (h1?: Function, h2?: Function): any => {
  if (h1 && h2) {
    return async function (this: any, ...args: any[]) {
      const result1 = await h1.apply(this, args)
      const result2 = await h2.apply(this, args)

      return result1 && result2 ? [...result1, ...result2] : result1 ?? result2
    }
  } else {
    return h1 ?? h2
  }
}

const mergeFunctionOptionsHooks = (h1?: Function, h2?: Function): any => {
  if (h1 && h2) {
    return async function (this: any, ...args: any[]) {
      const result1 = await h1.apply(this, args)
      const result2 = await h2.apply(this, args)

      return typeof result1 === 'function' && typeof result2 === 'function'
        ? function (this: any, ...args: any[]) {
            result1.apply(this, args)
            result2.apply(this, args)
          }
        : result1 ?? result2
    }
  } else {
    return h1 ?? h2
  }
}

export const mergeVitePlugin = (plugin: import('vite').Plugin, otherPlugin: Partial<import('vite').Plugin>) => {
  mergeRollupPlugin(plugin as any, otherPlugin as any)
  const { config, configResolved, configurePreviewServer, configureServer, handleHotUpdate } = plugin

  const {
    config: other$config,
    configResolved: other$configResolved,
    configurePreviewServer: other$configurePreviewServer,
    configureServer: other$configureServer,
    handleHotUpdate: other$handleHotUpdate
  } = otherPlugin

  otherPlugin.config = mergeOptionsHooks(other$config, config)
  otherPlugin.configResolved = mergeParallelHooks(other$configResolved, configResolved)
  otherPlugin.configureServer = mergeFunctionOptionsHooks(other$configureServer, configureServer)
  otherPlugin.configurePreviewServer = mergeFunctionOptionsHooks(other$configurePreviewServer, configurePreviewServer)
  otherPlugin.handleHotUpdate = mergeArrayOptionsHooks(other$handleHotUpdate, handleHotUpdate)
}
